package ms.unicorn.language.languagedef;

import java.util.List;

import ms.unicorn.modellanguage.LanguageElement;
import ms.unicorn.ui.layout.DotNetLayout;
import ms.unicorn.ui.layout.DotNetLayoutConstraint;
import ms.unicorn.util.ErrorHandler;
import ms.unicorn.util.ReflectionUtil;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gmf.runtime.draw2d.ui.figures.PolylineConnectionEx;
import org.eclipse.xtext.xbase.interpreter.IEvaluationContext;
import org.eclipse.xtext.xbase.interpreter.impl.DefaultEvaluationContext;
import org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter;
import org.eclipse.xtext.xbase.scoping.XbaseScopeProvider;

@SuppressWarnings("restriction")
public class FigureDefUtil {
	
	public static FigureContainer resolveFigure(LanguageElement element, FigureDef fig, List<Parameter> layoutParameter, EditPart editpart, Class<?> defaultFigureImplClass) {
		return resolveFigure(element, element.getLanguage().getContext(), null, fig, layoutParameter, editpart, defaultFigureImplClass);
	}
	
	
	/*public static int getFigureWidth(FigureDef figDef) {
		return figDef.isWidthSet() || figDef.isSizeSet() ? figDef.getWidth() :
					figDef.isInherited() ? getFigureWidth(figDef.getSuperElement()) : 0;
	}
	
	public static int getFigureHeight(FigureDef figDef) {
		return figDef.isHeightSet() || figDef.isSizeSet() ? figDef.getHeight() :
			figDef.isInherited() ? getFigureHeight(figDef.getSuperElement()) : 0;
	}*/
	
	@SuppressWarnings({"rawtypes"})
	protected static FigureContainer resolveFigure(LanguageElement element, IEvaluationContext context, IFigure parentFigure, 
					FigureDef figDef, List<Parameter> params, EditPart editpart, Class<?> defaultFigureImplClass) {
		FigureContainer figures = new FigureContainer();
		
		Class figClass = LanguageDefUtil.resolveImplClass(figDef, defaultFigureImplClass);
		IFigure figure;
		
		try {
			figure = (IFigure) figClass.newInstance();
			List<TagEntryDef> properties = TagDefUtil.getAllTagProperties(figDef);

			TagDefUtil.setProperties(figure, properties);
			ReflectionUtil.setPropertyValue(figure, "EditPart", editpart);
			
			Rectangle pos = ParameterUtil.getPosition(params, null);
			Dimension size = ParameterUtil.getSize(params, null);
				
			Rectangle r = new Rectangle(figure.getBounds());
			if (pos != null) {
				r.x = pos.x;
				r.y = pos.y;
			}
			if (size != null) {
				r.width = size.width;
				r.height = size.height;
			}
			if (pos != null || size != null)
				figure.setBounds(r);
			
			// append this figure into the parent figure
			if (parentFigure != null) {
				DotNetLayoutConstraint layoutData = new DotNetLayoutConstraint();

				XbaseUtil.interpreter = (XbaseInterpreter) element.getLanguage().getInterpreter();
				XbaseUtil.context = context;
				
				Boolean isPrimary = ParameterUtil.getParameter(params, ParameterType.PRIMARY, false);
				layoutData.setDock(ParameterUtil.getDock(params, DockType.NONE));
				
				Anchor anchor = ParameterUtil.getParameter(params, ParameterType.ANCHOR, null);
				if (anchor != null) 
					layoutData.setAnchor(anchor);
				
				Insets margin = ParameterUtil.getMargin(params, null);
				if (margin != null)
					layoutData.setMargin(margin);
				
				parentFigure.add(figure, layoutData);
				if (isPrimary)
					figures.setPrimaryFigure(figure);
			}
			
			if (!(figure instanceof PolylineConnectionEx)) {
				DotNetLayout layout = new DotNetLayout();
				figure.setLayoutManager(layout);
			}
			
			IEvaluationContext currentContext = new DefaultEvaluationContext(context);
			currentContext.newValue(XbaseScopeProvider.THIS, figure);
			
			for(SubFigure subfig: figDef.getChildren()) {
				FigureDef subFigureDef = LanguageDefUtil.resolveDefinition(subfig.getFigure()); 
				FigureContainer subfigure = resolveFigure(element, context, figure, 
						subFigureDef, subfig.getLayout(),  editpart, defaultFigureImplClass);
				figures.put(subfig.getName(), subfigure);
				if (subfigure.getPrimaryFigure() != null && figures.getPrimaryFigure() == null)
					figures.setPrimaryFigure(subfigure.getPrimaryFigure());
			}
				
			figures.setMainFigure(figure);
		} catch (Exception e) {
			ErrorHandler.handleException(e);
		}
		return figures;
	}	
}
